"""
农产品推荐系统 - Flask后端应用
================================

本模块是农产品价格分析和推荐系统的Flask后端应用，提供以下功能：
1. 农产品数据搜索和查询
2. 价格分布分析和可视化
3. 价格统计和对比分析
4. 价格预测分析
5. 近日均价展示
6. Excel数据导出
7. 外部系统集成

作者: 系统开发团队
版本: 1.0.0
日期: 2024
"""

# 导入必要的库
from flask import Flask, render_template, request, jsonify, send_file  # Flask核心组件
import requests  # HTTP请求库
import pandas as pd  # 数据处理库
import json  # JSON数据处理
import io  # 输入输出流处理
from datetime import datetime  # 日期时间处理
import plotly.express as px  # Plotly图表库
import plotly.graph_objects as go  # Plotly图形对象
from plotly.utils import PlotlyJSONEncoder  # Plotly JSON编码器

# 创建Flask应用实例
app = Flask(__name__)

# ==================== 应用配置 ====================
app.config['SECRET_KEY'] = 'agricultural_system_2024'  # 应用密钥，用于会话加密
app.config['EXTERNAL_SYSTEM_URL'] = 'http://192.168.43.230:8080/'  # 外部系统地址
app.config['API_BASE_URL'] = 'http://192.168.43.230:8080/api'  # API基础地址

# ==================== 模拟数据定义 ====================
# 注意：在实际项目中这些数据会从真实的API或数据库获取
MOCK_DATA = {
    # 产品分类列表
    'prod_categories': ['蔬菜', '水果', '粮食', '油料'],
    # 产品名称列表
    'products': ['苹果', '西红柿', '大米', '玉米', '土豆', '白菜'],
    # 表格数据 - 包含详细的农产品价格信息
    'table_data': [
        {
            'prodCat': '蔬菜',  # 一级分类
            'prodPcat': '叶菜类',  # 二级分类
            'prodName': '白菜',  # 产品名称
            'lowPrice': 2.5,  # 最低价格
            'avgPrice': 3.2,  # 平均价格
            'highPrice': 4.0,  # 最高价格
            'specInfo': '500g/袋',  # 规格信息
            'place': '山东',  # 产地
            'unitInfo': '元/斤',  # 单位信息
            'pubDate': '2024-01-15'  # 发布日期
        },
        {
            'prodCat': '水果',
            'prodPcat': '核果类',
            'prodName': '苹果',
            'lowPrice': 4.5,
            'avgPrice': 5.8,
            'highPrice': 7.2,
            'specInfo': '1kg/袋',
            'place': '陕西',
            'unitInfo': '元/斤',
            'pubDate': '2024-01-15'
        },
        {
            'prodCat': '粮食',
            'prodPcat': '谷物类',
            'prodName': '大米',
            'lowPrice': 2.8,
            'avgPrice': 3.5,
            'highPrice': 4.2,
            'specInfo': '5kg/袋',
            'place': '黑龙江',
            'unitInfo': '元/斤',
            'pubDate': '2024-01-15'
        }
    ]
}


# ==================== 工具函数 ====================

def get_api_data(endpoint, params=None):
    """
    从外部API获取数据的通用函数

    参数:
        endpoint (str): API端点路径
        params (dict): 请求参数

    返回:
        dict: API响应数据，失败时返回None
    """
    try:
        # 构建完整的API URL
        url = f"{app.config['API_BASE_URL']}/{endpoint}"
        # 发送GET请求，设置5秒超时
        response = requests.get(url, params=params, timeout=5)
        # 检查响应状态码
        if response.status_code == 200:
            return response.json()  # 返回JSON格式的响应数据
        else:
            return None  # 请求失败返回None
    except Exception as e:
        # 捕获所有异常（网络错误、超时等）
        print(f"API请求失败: {e}")
        return None


def create_price_chart(data, title, chart_type='line'):
    """
    创建价格图表的通用函数

    参数:
        data (list): 图表数据
        title (str): 图表标题
        chart_type (str): 图表类型 ('line' 或 'bar')

    返回:
        str: JSON格式的图表配置
    """
    # 根据图表类型创建不同的图表
    if chart_type == 'line':
        # 创建折线图
        fig = px.line(data, x='time', y='price', title=title,
                      color_discrete_sequence=['#2d5016'])  # 使用深绿色主题
    elif chart_type == 'bar':
        # 创建柱状图
        fig = px.bar(data, x='type', y='value', title=title,
                     color_discrete_sequence=['#2d5016'])

    # 统一配置图表样式
    fig.update_layout(
        plot_bgcolor='white',  # 图表背景色
        paper_bgcolor='white',  # 纸张背景色
        font=dict(color='#2d5016'),  # 字体颜色
        title_font_color='#2d5016'  # 标题字体颜色
    )
    # 将图表转换为JSON格式返回
    return json.dumps(fig, cls=PlotlyJSONEncoder)


# ==================== 页面路由 ====================

@app.route('/')
def index():
    """
    主页路由
    返回系统主页，展示系统概览和功能导航
    """
    return render_template('index.html')


@app.route('/data_search')
def data_search():
    """
    数据搜索页面路由
    返回数据搜索页面，提供农产品数据查询功能
    """
    return render_template('data_search.html',
                           categories=MOCK_DATA['prod_categories'])


@app.route('/price_distribution')
def price_distribution():
    """
    价格分布页面路由
    返回价格分布分析页面，展示价格变化趋势
    """
    return render_template('price_distribution.html')


@app.route('/price_statistics')
def price_statistics():
    """
    价格统计页面路由
    返回价格统计页面，展示各类农产品的价格对比
    """
    return render_template('price_statistics.html')


@app.route('/price_prediction')
def price_prediction():
    """
    价格预测页面路由
    返回价格预测页面，展示价格预测分析
    """
    return render_template('price_prediction.html')


@app.route('/recent_prices')
def recent_prices():
    """
    近日均价页面路由
    返回近日均价页面，展示近期价格变化
    """
    return render_template('recent_prices.html')


@app.route('/external_system')
def external_system():
    """
    外部系统跳转页面路由
    返回外部系统集成页面，提供系统跳转功能
    """
    return render_template('external_system.html')


# ==================== API接口 ====================

@app.route('/api/data/search')
def api_data_search():
    """
    数据搜索API接口

    功能：根据条件搜索农产品数据，支持分页

    请求参数:
        page (int): 页码，默认1
        size (int): 每页数量，默认20
        prodCat (str): 产品分类筛选
        prodName (str): 产品名称筛选

    返回:
        JSON格式的搜索结果，包含数据列表和分页信息
    """
    # 获取请求参数，设置默认值
    page = int(request.args.get('page', 1))
    size = int(request.args.get('size', 20))
    prod_cat = request.args.get('prodCat', '')
    prod_name = request.args.get('prodName', '')

    # 数据过滤处理
    filtered_data = MOCK_DATA['table_data']
    if prod_cat:
        # 按产品分类过滤
        filtered_data = [item for item in filtered_data if item['prodCat'] == prod_cat]
    if prod_name:
        # 按产品名称模糊搜索（不区分大小写）
        filtered_data = [item for item in filtered_data if prod_name.lower() in item['prodName'].lower()]

    # 分页处理
    start = (page - 1) * size
    end = start + size
    paginated_data = filtered_data[start:end]

    # 返回JSON格式的响应
    return jsonify({
        'code': 200,  # 状态码
        'message': '查询成功',  # 状态消息
        'data': {
            'records': paginated_data,  # 当前页数据
            'total': len(filtered_data),  # 总记录数
            'pageNum': page,  # 当前页码
            'pageSize': size  # 每页大小
        }
    })


@app.route('/api/data/categories')
def api_categories():
    """
    获取产品分类API接口

    功能：返回所有可用的产品分类列表

    返回:
        JSON格式的产品分类列表
    """
    return jsonify({
        'code': 200,
        'data': MOCK_DATA['prod_categories']
    })


@app.route('/api/price_distribution')
def api_price_distribution():
    """
    价格分布数据API接口

    功能：获取指定产品的价格分布数据，用于生成趋势图

    请求参数:
        product (str): 产品名称，默认'苹果'
        granularity (str): 时间粒度，默认'month'

    返回:
        JSON格式的价格分布数据和图表配置
    """
    # 获取请求参数
    product = request.args.get('product', '苹果')
    granularity = request.args.get('granularity', 'month')

    # 模拟价格分布数据（实际项目中从数据库获取）
    data = {
        '苹果': {
            'month': [
                {'time': '2024-01', 'price': 5.2},
                {'time': '2024-02', 'price': 5.5},
                {'time': '2024-03', 'price': 5.8},
                {'time': '2024-04', 'price': 6.0},
                {'time': '2024-05', 'price': 6.2}
            ]
        }
    }

    # 获取指定产品的数据
    chart_data = data.get(product, {}).get(granularity, [])
    # 生成图表配置
    chart_json = create_price_chart(chart_data, f'{product}价格分布')

    return jsonify({
        'code': 200,
        'data': chart_data,  # 原始数据
        'chart': chart_json  # 图表配置
    })


@app.route('/api/price_statistics')
def api_price_statistics():
    """
    价格统计数据API接口

    功能：获取各类农产品的价格统计信息

    请求参数:
        type (str): 统计类型，默认'avg'

    返回:
        JSON格式的统计数据
    """
    stat_type = request.args.get('type', 'avg')

    # 模拟统计数据
    data = {
        'avg': [
            {'type': '蔬菜', 'value': 3.5},
            {'type': '水果', 'value': 5.2},
            {'type': '粮食', 'value': 2.8},
            {'type': '油料', 'value': 4.1}
        ]
    }

    chart_data = data.get(stat_type, [])
    # 生成柱状图
    chart_json = create_price_chart(chart_data, '农产品价格统计', 'bar')

    return jsonify({
        'code': 200,
        'data': chart_data,
        'chart': chart_json
    })


@app.route('/api/price_prediction')
def api_price_prediction():
    """
    价格预测数据API接口

    功能：获取农产品价格预测数据，包含历史数据和预测数据

    请求参数:
        type (str): 产品类型，默认'蔬菜'
        days (int): 预测天数，默认7天

    返回:
        JSON格式的预测数据和图表配置
    """
    product_type = request.args.get('type', '蔬菜')
    days = int(request.args.get('days', 7))

    # 模拟历史数据和预测数据
    history_data = [3.2, 3.5, 3.8, 4.0, 4.2, 4.3, 4.5]  # 历史价格
    predict_data = [4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2]  # 预测价格

    # 创建双线图（历史数据 + 预测数据）
    fig = go.Figure()

    # 添加历史数据线
    fig.add_trace(go.Scatter(
        x=list(range(len(history_data))),
        y=history_data,
        mode='lines+markers',  # 线条+标记点
        name='历史价格',
        line=dict(color='#2d5016', width=3)  # 深绿色实线
    ))

    # 添加预测数据线
    fig.add_trace(go.Scatter(
        x=list(range(len(history_data), len(history_data) + len(predict_data))),
        y=predict_data,
        mode='lines+markers',
        name='预测价格',
        line=dict(color='#8b4513', width=3, dash='dash')  # 棕色虚线
    ))

    # 配置图表样式
    fig.update_layout(
        title=f'{product_type}价格预测',
        plot_bgcolor='white',
        paper_bgcolor='white',
        font=dict(color='#2d5016'),
        title_font_color='#2d5016'
    )

    return jsonify({
        'code': 200,
        'chart': json.dumps(fig, cls=PlotlyJSONEncoder)
    })


@app.route('/api/recent_prices')
def api_recent_prices():
    """
    近日均价数据API接口

    功能：获取指定产品的近日价格数据

    请求参数:
        type (str): 产品类型，默认'蔬菜'
        days (int): 天数，默认7天

    返回:
        JSON格式的近日价格数据
    """
    product_type = request.args.get('type', '蔬菜')
    days = int(request.args.get('days', 7))

    # 模拟近日价格数据
    prices = [3.2, 3.5, 3.8, 4.0, 4.2, 4.3, 4.5]
    # 格式化数据为图表所需格式
    data = [{'time': f'第{i + 1}天', 'price': price} for i, price in enumerate(prices[:days])]

    # 生成图表配置
    chart_json = create_price_chart(data, f'{product_type}近日均价')

    return jsonify({
        'code': 200,
        'data': data,
        'chart': chart_json
    })


@app.route('/api/check_external_system')
def api_check_external_system():
    """
    检查外部系统状态API接口

    功能：检查外部系统是否可访问

    返回:
        JSON格式的系统状态信息
    """
    try:
        # 尝试访问外部系统
        response = requests.get(app.config['EXTERNAL_SYSTEM_URL'], timeout=3)
        accessible = response.status_code == 200  # 判断是否可访问
    except Exception as e:
        # 访问失败
        print(f"外部系统检查失败: {e}")
        accessible = False

    return jsonify({
        'code': 200,
        'accessible': accessible  # 系统可访问状态
    })


# ==================== 文件导出功能 ====================

@app.route('/export_excel')
def export_excel():
    """
    Excel文件导出接口

    功能：将搜索结果导出为Excel文件

    请求参数:
        prodCat (str): 产品分类筛选
        prodName (str): 产品名称筛选

    返回:
        Excel文件下载
    """
    try:
        # 获取搜索参数
        prod_cat = request.args.get('prodCat', '')
        prod_name = request.args.get('prodName', '')

        # 数据过滤（与搜索API相同的逻辑）
        filtered_data = MOCK_DATA['table_data']
        if prod_cat:
            filtered_data = [item for item in filtered_data if item['prodCat'] == prod_cat]
        if prod_name:
            filtered_data = [item for item in filtered_data if prod_name.lower() in item['prodName'].lower()]

        # 创建Pandas DataFrame
        df = pd.DataFrame(filtered_data)

        # 创建Excel文件
        output = io.BytesIO()  # 内存文件流
        with pd.ExcelWriter(output, engine='openpyxl') as writer:
            # 将数据写入Excel工作表
            df.to_excel(writer, sheet_name='农产品数据', index=False)

        # 重置文件指针到开始位置
        output.seek(0)

        # 生成文件名（包含时间戳）
        filename = f'农产品数据_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx'

        # 返回文件下载响应
        return send_file(
            output,
            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            as_attachment=True,  # 作为附件下载
            download_name=filename
        )
    except Exception as e:
        # 异常处理
        print(f"Excel导出失败: {e}")
        return jsonify({'error': str(e)}), 500


# ==================== 应用启动 ====================

if __name__ == '__main__':
    """
    应用启动入口

    启动Flask开发服务器，监听所有网络接口的5000端口
    启用调试模式，便于开发调试
    """
    app.run(debug=True, host='0.0.0.0', port=5000) 